{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#   [Py4Hw User Guide](../UserGuide.ipynb)> 8.1 Dealing with unique instances, unique blocks and parametetric blocks\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In classic HDL languages you usually create an HDL design file that contains a module.\n",
    "Diferents levels of complexity can affect a HDL module. The following list describe the typical levels you can find, by order of complexity.\n",
    "\n",
    "- The module has a fixed interface, all input and output signals have a given width and no parameters exist\n",
    "- Parameters are used to define wire widths or simple things such as constant values.\n",
    "- Parameters are used in conjunction with generative clasules to create different hardware subcircuits depending on them\n",
    "\n",
    "On the other hand, in py4hw the designer never specifies the widths of the signals, they are inferred during runtime when instantiating the circuit. This does not mean that the designer cannot enforce certain widths on signals, but this must be done during runtime (usually by raising exceptions when invalid parameters are observed).\n",
    "\n",
    "Moreover, the interface of circuits is totally defined during runtime. This means that in some circumstances a circuit can create some few inputs and outputs and in other circumstances can create hundreds of them. This flexibility is not present in many HDL frameworks, with some exceptions. For instance, this is possible in Chisel.\n",
    "\n",
    "\n",
    "The challenge, then, is : how to procude RTL from those generic py4hw descriptions?\n",
    "\n",
    "The easy option _currently implemented_ is to generate a different RTL file for each logic instance of the circuit.\n",
    "\n",
    "This option has the negative effect of generating very large HDL descriptions with unnecessary simple circuit duplications. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<py4hw.schematic.MatplotlibRender at 0x253625ff670>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 368x210 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import py4hw\n",
    "\n",
    "class ExampleChild(py4hw.Logic):\n",
    "    def __init__(self, parent, name, a, b, r):\n",
    "        super().__init__(parent, name)\n",
    "        \n",
    "        self.addIn('a', a)\n",
    "        self.addIn('b', b)\n",
    "        self.addOut('r', r)\n",
    "        \n",
    "        py4hw.And2(self, 'r', a, b, r)\n",
    "\n",
    "\n",
    "class Example(py4hw.Logic):\n",
    "    def __init__(self, parent, name, a, b, c, r):\n",
    "        super().__init__(parent, name)\n",
    "        \n",
    "        self.addIn('a', a)\n",
    "        self.addIn('b', b)\n",
    "        self.addIn('C', c)\n",
    "        self.addOut('r', r)\n",
    "        \n",
    "        d = self.wire('d', r.getWidth())\n",
    "        \n",
    "        ExampleChild(self, 'e1', a, b, d)\n",
    "        ExampleChild(self, 'e2', d, c, r)\n",
    "\n",
    "sys = py4hw.HWSystem()\n",
    "\n",
    "a = sys.wire('a')\n",
    "b = sys.wire('b')\n",
    "c = sys.wire('c')\n",
    "r = sys.wire('r')\n",
    "\n",
    "dut = Example(sys, 'example', a, b, c,r)\n",
    "\n",
    "py4hw.Schematic(dut).drawAll()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we generate the Verilog for this circuit multiple modules will be generated for each instance of the child element.\n",
    "This happens because py4hw does not know is this child circuit is exactly the same. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "// This file was automatically created by py4hw RTL generator\n",
      "module Example (\n",
      "\tinput  a,\n",
      "\tinput  b,\n",
      "\tinput  C,\n",
      "\toutput  r);\n",
      "wire w_d;\n",
      "\n",
      "ExampleChild_253625fdb40 i_e1(.a(a),.b(b),.r(w_d));\n",
      "ExampleChild_253625fdb10 i_e2(.a(w_d),.b(C),.r(r));\n",
      "endmodule\n",
      "\n",
      "// This file was automatically created by py4hw RTL generator\n",
      "module ExampleChild_253625fdb40 (\n",
      "\tinput  a,\n",
      "\tinput  b,\n",
      "\toutput  r);\n",
      "\n",
      "assign r = a & b;\n",
      "endmodule\n",
      "\n",
      "// This file was automatically created by py4hw RTL generator\n",
      "module ExampleChild_253625fdb10 (\n",
      "\tinput  a,\n",
      "\tinput  b,\n",
      "\toutput  r);\n",
      "\n",
      "assign r = a & b;\n",
      "endmodule\n",
      "\n"
     ]
    }
   ],
   "source": [
    "rtl = py4hw.VerilogGenerator(dut)\n",
    "print(rtl.getVerilogForHierarchy())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Structure Names ###\n",
    "\n",
    "A method to avoid this is that the designer provides a unique name (structure name) for every combination of parameters that should create a reusable module to avoid creating a module for every instance.\n",
    "In the former example we could do:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "// This file was automatically created by py4hw RTL generator\n",
      "module Example (\n",
      "\tinput  a,\n",
      "\tinput  b,\n",
      "\tinput  C,\n",
      "\toutput  r);\n",
      "wire w_d;\n",
      "\n",
      "Child1 i_e1(.a(a),.b(b),.r(w_d));\n",
      "Child1 i_e2(.a(w_d),.b(C),.r(r));\n",
      "endmodule\n",
      "\n",
      "// This file was automatically created by py4hw RTL generator\n",
      "module Child1 (\n",
      "\tinput  a,\n",
      "\tinput  b,\n",
      "\toutput  r);\n",
      "\n",
      "assign r = a & b;\n",
      "endmodule\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 368x210 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "class ExampleChild(py4hw.Logic):\n",
    "    def __init__(self, parent, name, a, b, r):\n",
    "        super().__init__(parent, name)\n",
    "        \n",
    "        self.addIn('a', a)\n",
    "        self.addIn('b', b)\n",
    "        self.r = self.addOut('r', r)\n",
    "        \n",
    "        py4hw.And2(self, 'r', a, b, r)\n",
    "        \n",
    "    def structureName(self):\n",
    "        return 'Child{}'.format(r.getWidth())\n",
    "\n",
    "\n",
    "class Example(py4hw.Logic):\n",
    "    def __init__(self, parent, name, a, b, c, r):\n",
    "        super().__init__(parent, name)\n",
    "        \n",
    "        self.addIn('a', a)\n",
    "        self.addIn('b', b)\n",
    "        self.addIn('C', c)\n",
    "        self.addOut('r', r)\n",
    "        \n",
    "        d = self.wire('d', r.getWidth())\n",
    "        \n",
    "        ExampleChild(self, 'e1', a, b, d)\n",
    "        ExampleChild(self, 'e2', d, c, r)\n",
    "\n",
    "sys = py4hw.HWSystem()\n",
    "\n",
    "a = sys.wire('a')\n",
    "b = sys.wire('b')\n",
    "c = sys.wire('c')\n",
    "r = sys.wire('r')\n",
    "\n",
    "dut = Example(sys, 'example', a, b, c,r)\n",
    "\n",
    "py4hw.Schematic(dut).drawAll()\n",
    "\n",
    "rtl = py4hw.VerilogGenerator(dut)\n",
    "print(rtl.getVerilogForHierarchy())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
